package com.person.yhzs.util;


import com.person.yhzs.common.Constants;
import com.person.yhzs.exception.BaseException;
import com.person.yhzs.exception.InvalidDataException;
import com.person.yhzs.user.entity.dto.FileDto;
import com.person.yhzs.user.entity.vo.FileVo;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.io.CopyStreamException;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.apache.tomcat.util.http.fileupload.InvalidFileNameException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.SocketException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * FTP 工具类
 *
 * @author Ry Huang
 * @date 2021-09-15
 */
public class FtpUtil {
    final static Logger LOGGER = LoggerFactory.getLogger(FtpUtil.class);
    public static ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();

    /**
     * WINDOWS 将此配置改成GBK
     * Linux 将此配置改成UTF-8
     */
    static String CHARSET_UTF8_OR_GBK = "UTF-8";
    /**
     * window
     */
    static String CHARSET_ISO = "ISO-8859-1";
    /**
     * 路径分隔符
     */
    private final String SEPARATOR_STR = "/";

    /**
     * 点
     */
    private final String DOT_STR = ".";

    @Value("${ftp.host:192.168.0.2}")
    String ftpHost;
    @Value("${ftp.port:21}")
    Integer ftpPort;
    @Value("${ftp.username:ftpuser}")
    String ftpUsername;
    @Value("${ftp.password:ftpuser}")
    String ftpPassword;
    @Value("${ftp.folder:/ftpfile}")
    String ftpFolder;
    @Value("${ftp.nginx:http://192.168.0.2:9999/resource/}")
    String nginxServer;

    static final String DEFAULT_PIC_TYPE = "png";
    static final String DEFAULT_WEB_UNKNOWN_TYPE = "application/octet-stream";


    public String getNginxPath() {
        return nginxServer;
    }

    public String getBaseFolder() {
        return ftpFolder;
    }


    /**
     * 获取FTPClient对象
     *
     * @param ftpHost     服务器IP
     * @param ftpPort     服务器端口号
     * @param ftpUserName 用户名
     * @param ftpPassword 密码
     * @return FTPClient
     */
    private FTPClient getFTPClient(String ftpHost, int ftpPort, String ftpUserName, String ftpPassword) {
        LOGGER.info("ftpHost:{}, ftpPort{}, name:{}, password:{}", ftpHost, ftpPort, ftpUserName, ftpPassword);
        FTPClient ftp = null;
        try {
            ftp = new FTPClient();
            ftp.connect(ftpHost, ftpPort);
            ftp.login(ftpUserName, ftpPassword);
            ftp.setConnectTimeout(5000);
            ftp.setControlEncoding(CHARSET_UTF8_OR_GBK);
            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                LOGGER.info("未连接到FTP，用户名或密码错误");
                ftp.disconnect();
            } else {
                LOGGER.info("FTP连接成功");
            }
        } catch (SocketException e) {
            e.printStackTrace();
            LOGGER.info("FTP的IP地址可能错误");
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.info("FTP的端口可能错误");
        }
        return ftp;
    }

    public boolean buildFtpClientCode(InputStream in, String taskId) {
        if (map.containsKey(taskId)) {
            if (in != null) {
                map.put(taskId, in);
                return true;
            }
        }
        return false;
    }

    /**
     * 关闭FTP方法
     *
     * @return
     */
    public boolean closeFTP(FTPClient ftpClient) {
        try {
            if (ftpClient != null) {
                ftpClient.logout();
            }
            return true;
        } catch (Exception e) {
            LOGGER.error("FTP关闭失败");
            return false;
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ioe) {
                    LOGGER.error("FTP关闭失败");
                }
            }
        }
    }

    public boolean distinctFtpClient(String taskId) {
        if (map.containsKey(taskId)) {
            try {
                Object o = map.get(taskId);
                if (o instanceof String) {
                    System.err.println("未执行到建立连接，直接中断文件上传");
                    return true;
                }
                InputStream in = (InputStream) o;
                if (in != null) {
                    in.close();
                    System.err.println("已经建立ftpClient连接，关闭文件输入流成功");
                    return true;
                }
            } catch (IOException e) {
                e.printStackTrace();
                System.out.println("关闭文件输入流出现异常");
            } finally {
                map.remove(taskId);
                System.err.println("移除任务id " + taskId + "成功");
            }
        }
        return false;
    }

    /**
     * FTP文件上传方法
     *
     * @param filePath
     * @param ftpFolder
     * @return
     */
    public boolean uploadFile(String filePath, String ftpFolder) {
        boolean uploaded = false;
        InputStream in = null;
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        try {
            //检查并目录
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            if (!ftpClient.changeWorkingDirectory(ftpFolder)) {
                ftpClient.makeDirectory(ftpFolder);
            }
            ftpClient.changeWorkingDirectory(ftpFolder);

            //上传文件
            File file = new File(filePath);
            in = new FileInputStream(file);
            if (StringUtils.isBlank(ftpFolder)) {
                ftpFolder = File.separator;
            }
            String tempName = new StringBuilder()
                    .append(ftpFolder.startsWith(File.separator) ? "" : File.separator)
                    .append(ftpFolder)
                    .append(File.separator)
                    .append(file.getName())
                    .toString();
            uploaded = ftpClient.storeFile(new String(tempName.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO), in);
            LOGGER.info("文件上传 : " + uploaded);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error("上传失败");
        } finally {
            closeFTP(ftpClient);
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return uploaded;
    }

    /**
     * 将本地文件上传到文件服务器
     */
    public String uploadFromLocalFile(String localFilePath, String folder) throws IOException {
        if (StringUtils.isBlank(localFilePath)) {
            throw new InvalidDataException("无效的文件路径");
        }
        File file = new File(localFilePath);
        if (!file.exists() || !file.isFile()) {
            throw new BaseException("未发现指定的待上传文件");
        }
        if (StringUtils.isBlank(folder)) {
            throw new BaseException("无效的folder");
        }

        int index = localFilePath.lastIndexOf('.');
        int len = localFilePath.length();
        if (index == -1 || index == len - 1) {
            throw new BaseException("未知的文件类型!");
        }
        String fileType = localFilePath.substring(index, len);
        InputStream inputStream = new FileInputStream(file);
        return uploadToServer(inputStream, folder, fileType);
    }

    /**
     * 从Servlet上传文件到FTP服务.
     *
     * @param file      MultipartFile 文件输入流
     * @param ftpFolder 保存在FTP服务器的文件夹
     * @return 前端访问地址
     * @throws IOException
     */
    public String uploadToFtpFromServlet(MultipartFile file, String ftpFolder) throws IOException {
        if (file == null) {
            throw new FileNotFoundException("未发现上传文件");
        }
        String originalName = file.getOriginalFilename();
        String fileType = null;
        if (StringUtils.isNotBlank(originalName)) {
            fileType = originalName.substring(originalName.lastIndexOf('.'), originalName.length());
        }
        if (StringUtils.isBlank(fileType)) {
            if (DEFAULT_WEB_UNKNOWN_TYPE.equals(file.getName())) {
                fileType = "." + DEFAULT_PIC_TYPE;
            } else {
                throw new InvalidFileNameException(originalName, "未知的文件类型!");
            }
        }
        return uploadToServer(file.getInputStream(), ftpFolder, fileType);
    }

    String uploadToServer(InputStream input, String folder, String fileType) {
        String randomStr = String.valueOf(Math.random());
        String name = new StringBuilder("-")
                .insert(0, String.valueOf(System.currentTimeMillis()))
                .append(randomStr.substring(randomStr.indexOf('.') + 1))
                .append(fileType).toString();

        if (uploadFileStream(name, folder, input)) {
            return new StringBuilder(nginxServer)
                    .append(folder.replace('\\', '/')).append("/")
                    .append(name).toString();
        }
        return null;
    }

    /**
     * FTP字节流上传方法
     *
     * @param fileName  文件名
     * @param ftpFolder 在ftp中的目录
     * @param input     输入字节流
     * @return 服务器文件全路径
     */
    public boolean uploadFileStream(String fileName, String ftpFolder, InputStream input) {
        if (StringUtils.isBlank(fileName) || StringUtils.isBlank(ftpFolder) || input == null) {
            LOGGER.error("fileName、ftpFolder、输入流都不能为空");
            return false;
        }
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        try {
            if (!ftpClient.changeWorkingDirectory(ftpFolder)) {
                //如果目录不存在创建目录
                String[] dirs = ftpFolder.replace(File.separatorChar, File.pathSeparatorChar).split(File.pathSeparator);
                String tempPath = "";
                for (String dir : dirs) {
                    if (null == dir || "".equals(dir)) {
                        continue;
                    }
                    tempPath += File.separator + dir;
                    if (!ftpClient.changeWorkingDirectory(dir)) {
                        if (ftpClient.makeDirectory(dir)) {
                            ftpClient.changeWorkingDirectory(dir);
                        } else {
                            LOGGER.error("创建目录失败：{}", tempPath);
                            return false;
                        }
                    }
                }
            }
            //设置上传文件的类型为二进制类型
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding(CHARSET_UTF8_OR_GBK);

            //上传文件
            ftpClient.enterLocalPassiveMode();
            String nameStr = new String(fileName.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            if (!ftpClient.storeFile(nameStr, input)) {
                LOGGER.error("存储文件失败：{}", nameStr);
                return false;
            }
            input.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
            try {
                if (input != null) {
                    input.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 批量删除FTP上指定文件.
     *
     * @param deleteUrls 将要被删除的文件列表.
     * @return 返回删除失败的文件列表。
     */
    public Set<String> deleteFiles(Set<String> deleteUrls) {
        Set<String> failUrls = new HashSet<>();
        if (CollectionUtils.isEmpty(deleteUrls)) {
            return failUrls;
        }
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        deleteUrls.forEach(url -> {
            String u = url.toLowerCase().startsWith("http") ? getPathFromUrl(url) : url.replace("\\", "/");
            try {
                if (!ftpClient.deleteFile(new String(u.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO))) {
                    failUrls.add(url);
                }
            } catch (Exception e) {
                failUrls.add(url);
                e.printStackTrace();
            }
        });
        closeFTP(ftpClient);
        return failUrls;
    }

    /**
     * 删除文件服务器上的文件. 仅支持下面两种格式。
     * 如：http://localhost:8000/risk/pdf/1614839404263-17215614490331932.pdf
     * 或者 /risk/pdf/1614839404263-17215614490331932.pdf
     *
     * @param fileUrl 文件路径及文件名
     * @return 前端访问地址
     * @throws IOException
     */
    boolean deleteFile(String fileUrl) {
        if (StringUtils.isBlank(fileUrl)) {
            throw new InvalidDataException("无效的文件地址");
        }
        if (fileUrl.toLowerCase().startsWith("http")) {
            fileUrl = getPathFromUrl(fileUrl);
        } else {
            fileUrl = fileUrl.replace("\\", "/");
        }
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        try {
            return ftpClient.deleteFile(new String(fileUrl.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return false;
    }

    String getPathFromUrl(String url) {
        int index = url.indexOf("//");
        //加2表示跳过”//“
        if (index < 0 || (index += 2) >= url.length()) {
            throw new InvalidDataException("无效的url");
        }
        url = url.substring(index);
        index = url.indexOf("/");
        if (index < 0 || (index + 1) >= url.length()) {
            throw new InvalidDataException("无效的url");
        }
        return url.substring(index + 1);
    }
    //--------------------------------新增----------------------------------//

    /**
     * FTP字节流上传方法
     *
     * @param fileName  文件名
     * @param ftpFolder 在ftp中的目录
     * @param input     输入字节流
     * @return 服务器文件全路径
     */
    public boolean uploadFileStreamNew(String fileName, String ftpFolder, InputStream input, String taskId) {
        if (StringUtils.isBlank(fileName) || StringUtils.isBlank(ftpFolder) || input == null) {
            LOGGER.error("fileName、ftpFolder、输入流都不能为空");
            return false;
        }
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        //装进盒子 方便中断进程
        buildFtpClientCode(input, taskId);
        try {
            ftpFolder = new String(ftpFolder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            if (!ftpClient.changeWorkingDirectory(ftpFolder)) {
                //如果目录不存在创建目录
                String[] dirs = ftpFolder.replace(File.separatorChar, File.pathSeparatorChar).split(File.pathSeparator);
                String tempPath = "";
                for (String dir : dirs) {
                    if (null == dir || "".equals(dir)) {
                        continue;
                    }
                    tempPath += File.separator + dir;
                    if (!ftpClient.changeWorkingDirectory(dir)) {
                        if (ftpClient.makeDirectory(dir)) {
                            ftpClient.changeWorkingDirectory(dir);
                        } else {
                            LOGGER.error("创建目录失败：{}", tempPath);
                            return false;
                        }
                    }
                }
            }
            //设置上传文件的类型为二进制类型
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding(CHARSET_UTF8_OR_GBK);
            //上传文件
            ftpClient.enterLocalPassiveMode();
            String nameStr = new String(fileName.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            if (!map.containsKey(taskId)) {
                System.out.println("上传任务被终止" + taskId);
                return false;
            }
            if (!ftpClient.storeFile(nameStr, input)) {
                LOGGER.error("存储文件失败：{}", nameStr);
                return false;
            }
            input.close();
            return true;
        } catch (CopyStreamException e) {
            //捕获此异常说明 中断流操作  ftp遗留未完整的文件 故删除不完整的文件
            if (ftpFolder.equals("/")) {
                System.out.println(deleteFile(ftpFolder + fileName) ? "删除上传失败的临时文件" + ftpFolder + fileName + "成功" : "删除上传失败的临时文件" + ftpFolder + fileName + "失败");
            } else {
                System.out.println(deleteFile(ftpFolder + "/" + fileName) ? "删除上传失败的临时文件" + ftpFolder + "/" + fileName + "成功" : "删除上传失败的临时文件" + ftpFolder + "/" + fileName + "失败");
            }
            System.err.println("强行中断文件流成功");
            return false;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //未收到终止上传命令自动销毁任务id
            if (map.containsKey(taskId)) {
                map.remove(taskId);
                System.err.println("未收到终止上传命令自动销毁任务id" + taskId);
            }
            closeFTP(ftpClient);
            try {
                if (input != null) {
                    input.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return false;
    }


    /**
     * 获取文件夹中的文件列表 不包含子文件的内容
     *
     * @param folder
     * @return
     */
    public List<FTPFile> listFilesByFolder(String folder) {
        try {
            folder = StringUtils.isBlank(folder) ? null : new String(folder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        List<FTPFile> list = null;
        try {
            FTPFile[] ftpFiles = ftpClient.listFiles(folder);
            if (ftpFiles != null && ftpFiles.length > 0) {
                list = new ArrayList<>(ftpFiles.length);
                Collections.addAll(list, ftpFiles);
            } else {
                list = new ArrayList<>(0);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return list;

    }

    /**
     * 获取文件夹中的文件列表 不包含子文件的内容
     *
     * @param folder
     * @return
     */
    public List<FTPFile> listFilesByFolder(String folder, FTPClient ftpClient) {
        try {
            folder = StringUtils.isBlank(folder) ? null : new String(folder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        List<FTPFile> list = null;
        try {
            FTPFile[] ftpFiles = ftpClient.listFiles(folder);
            if (ftpFiles != null && ftpFiles.length > 0) {
                list = new ArrayList<>(ftpFiles.length);
                Collections.addAll(list, ftpFiles);
            } else {
                list = new ArrayList<>(0);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;

    }

    /**
     * 获取文件夹中的文件列表 不包含子文件的内容
     *
     * @param folder
     * @return
     */
    public List<FileVo> buildFileVo(String folder) {
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        List<FileVo> fileVoList = new ArrayList<>();
        try {
            List<FTPFile> ftpFiles = listFilesByFolder(folder, ftpClient);
            if (CollectionUtils.isEmpty(ftpFiles)) {
                return fileVoList;
            }
            for (FTPFile item : ftpFiles) {
                FileVo fileVo = new FileVo();
                BeanUtils.copyProperties(item, fileVo);
                fileVo.setCreateTime(item.getTimestamp().getTime());
                String parentPath = StringUtils.isBlank(folder) ? "/" : folder;
                if (item.isDirectory()) {
                    //如果是文件夹  看他下级有没有文件夹 提前打个标识方便前端渲染页面
                    fileVo.setFolder(parentPath);
                    String absolutePath = parentPath.equals("/") ? parentPath + item.getName() : parentPath + "/" + item.getName();
                    fileVo.setAbsolutePath(absolutePath);
                    List<FTPFile> childFtpFile = listFilesByFolder(absolutePath, ftpClient);
                    if (CollectionUtils.isEmpty(childFtpFile)) {
                        fileVo.setHaveChild(false);
                    } else {
                        childFtpFile.forEach(child -> {
                            if (child.isDirectory()) {
                                fileVo.setHaveChild(true);
                            }
                        });
                    }
                } else {
                    String name = item.getName();
                    int index = name.lastIndexOf(".");
                    String suffix = name.substring(index + 1);
                    fileVo.setSuffixName(suffix);
                    fileVo.setFolder(parentPath);
                    fileVo.setAbsolutePath((parentPath.equals("/") ? parentPath + item.getName() : parentPath + "/" + item.getName()));
                }
                fileVoList.add(fileVo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return fileVoList;
    }


    /**
     * 从Servlet上传文件到FTP服务(针对西藏法院ftp文件做特殊处理)
     *
     * @param file      MultipartFile 文件输入流
     * @param ftpFolder 保存在FTP服务器的文件夹
     * @return 前端访问地址
     * @throws IOException
     */
    public String uploadToFtpFromServletNew(MultipartFile file, String ftpFolder, Integer insertOrCover, boolean exist, String taskId) throws IOException {
        if (file == null) {
            throw new FileNotFoundException("未发现上传文件");
        }
        String originalName = file.getOriginalFilename();
        String fileType = null;
        if (StringUtils.isNotBlank(originalName)) {
            fileType = originalName.substring(originalName.lastIndexOf('.'), originalName.length());
        }
        if (StringUtils.isBlank(fileType)) {
            if (DEFAULT_WEB_UNKNOWN_TYPE.equals(file.getName())) {
                fileType = "." + DEFAULT_PIC_TYPE;
            } else {
                throw new InvalidFileNameException(originalName, "未知的文件类型!");
            }
        }
        //新增文件
        if (insertOrCover == Constants.FILE_INSERT) {
            //文件是否存在
            if (exist) {
                String currTime = com.person.yhzs.util.DateUtil.getCurrTime();
                originalName = originalName.substring(0, originalName.lastIndexOf(".")) + "_" + currTime;
            } else {
                originalName = originalName.substring(0, originalName.lastIndexOf("."));
            }
        } else {
            //覆盖文件
            originalName = originalName.substring(0, originalName.lastIndexOf("."));
        }
        return uploadToServerNew(file.getInputStream(), ftpFolder, fileType, originalName, taskId);
    }

    String uploadToServerNew(InputStream input, String folder, String fileType, String name, String taskId) {
        name = name + fileType;
        if (uploadFileStreamNew(name, folder, input, taskId)) {
            if (folder.equals("/")) {
                return new StringBuilder(nginxServer)
                        //.append(folder.replace('\\', '/')).append("/")
                        .append(name).toString();
            } else {

                return new StringBuilder(nginxServer)
                        .append(folder.replace('\\', '/')).append("/")
                        .append(name).toString();
            }
        }
        return null;
    }

    /**
     * 创建文件夹
     *
     * @param ftpFolder
     * @return
     */
    public boolean buildDirectory(String ftpFolder) {
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        try {
            String folder = new String(ftpFolder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            if (!ftpClient.changeWorkingDirectory(folder)) {
                //如果目录不存在创建目录
                String[] dirs = folder.replace(File.separatorChar, File.pathSeparatorChar).split(File.pathSeparator);
                String tempPath = "";
                for (String dir : dirs) {
                    if (null == dir || "".equals(dir)) {
                        continue;
                    }
                    tempPath += File.separator + dir;
                    if (!ftpClient.changeWorkingDirectory(dir)) {
                        if (ftpClient.makeDirectory(dir)) {
                            ftpClient.changeWorkingDirectory(dir);
                        } else {
                            LOGGER.error("创建目录失败：{}", tempPath);
                            return false;
                        }
                    }
                }
            } else {
                //存在  抛出提示
                throw new BaseException("文件夹已存在 请勿重复创建");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return true;
    }

    /**
     * 删除文件夹
     *
     * @param folder
     * @return
     */
    public boolean delDirectory(String folder) {
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        boolean b = false;
        try {
            //删除文件夹
            b = delDirectory(folder, ftpClient);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return b;
    }

    /**
     * 删除指定文件夹
     *
     * @param folder    文件夹绝对路径
     * @param ftpClient ftpclient
     * @return
     */
    public boolean delDirectory(String folder, FTPClient ftpClient) {
        try {
            String pathName = new String(folder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            ftpClient.changeWorkingDirectory(pathName);
            if (ftpClient.removeDirectory(pathName)) {
                return true;
            }
            FTPFile[] ftpFiles = ftpClient.listFiles(pathName);
            List<FTPFile> ftpFileList = Arrays.asList(ftpFiles);
            for (FTPFile ftpFile : ftpFileList) {
                if (ftpFile.isFile()) {
                    ftpClient.changeWorkingDirectory(pathName);
                    ftpClient.deleteFile(new String(ftpFile.getName().getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
                } else {
                    ftpClient.changeWorkingDirectory(pathName);
                    boolean b = ftpClient.removeDirectory(pathName + new String(ftpFile.getName().getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO) + "/");
                    if (!b) {
                        //递归查询子文件夹中文件/文件夹 作递归删除
                        delDirectory(folder + ftpFile.getName() + "/", ftpClient);
                        ftpClient.changeWorkingDirectory(pathName);
                        //删除子文件夹后  删除当前文件夹
                        ftpClient.removeDirectory(pathName + new String(ftpFile.getName().getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO) + "/");
                    }
                }
            }
            //删除当前文件夹
            ftpClient.changeWorkingDirectory(folder);
            return ftpClient.removeDirectory(new String(folder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 文件下载
     *
     * @param fileName
     * @param response
     * @return
     */

    public void downloadFtpFile(String fileName, HttpServletResponse response) {
        FTPClient ftpClient = null;
        OutputStream os = null;
        InputStream in = null;
        try {
            ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            String pathname = new String(fileName.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            ftpClient.changeWorkingDirectory(pathname);
            FTPFile[] ftpFiles = ftpClient.listFiles(pathname);
            List<FTPFile> ftpFileList = Arrays.asList(ftpFiles);
            if (CollectionUtils.isEmpty(ftpFileList)) {
                throw new BaseException("文件不存在");
            }
            if (ftpFileList.size() == 1) {
                FTPFile ftpFile = ftpFileList.get(0);
                String name = ftpFile.getName();
                in = ftpClient.retrieveFileStream(pathname);
                //处理中文乱码
                response.setHeader("Content-type", "text/html;charset=utf-8");
                // response.setContentType("text/html;charset=utf-8");
                //设置文件ContentType类型，这样设置，会自动判断下载文件类型
                response.setContentType("multipart/form-data");
                //设置文件头：最后一个参数是设置下载文件名
                response.setHeader("Content-Disposition", "attachment;filename=" + name);
                response.setContentLengthLong(ftpFile.getSize());
                os = response.getOutputStream();
                /*完成文件传输必须调用completependingcommand和检查它的返回值来验证成功。如果没有这样做，后续命令可能会意外地出错
                completePendingCommand()会一直在等FTP Server返回226 Transfer complete，但是FTP Server只有在接受到InputStream执行close方法时才会返回。
                所以先要执行close方法*/
                // byte[] bytes = FtpUtil.toByteArray(in);
                // os.write(bytes);
                subsectionWriteFile(os, in);
                if (in != null) {
                    //必须先关流
                    in.close();
                }
                ftpClient.completePendingCommand();
            } else {
                throw new BaseException("文件路径不正确");
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                if (os != null) {
                    os.close();
                }
                if (ftpClient != null) {
                    closeFTP(ftpClient);
                }
                System.out.println("文件下载完成");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static byte[] toByteArray(InputStream input) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            output.write(buffer, 0, n);
        }
        return output.toByteArray();
    }

    /**
     * 删除文件
     *
     * @param url 绝对地址
     * @return
     */
    public boolean delFile(String url) {
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        try {
            return ftpClient.deleteFile(new String(url.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return false;
    }

    /**
     * 文件重命名
     *
     * @param folder    绝对地址
     * @param newFolder 绝对地址
     * @return
     */
    public boolean rename(String folder, String newFolder) {
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        try {
            String oldFolder = new String(folder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            String newFolderOne = new String(newFolder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            return ftpClient.rename(oldFolder, newFolderOne);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return false;

    }

    /**
     * 获取所有文件列表
     *
     * @param folder
     * @return
     */
    public FileDto getFileList(String folder) {
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        FileDto fileDto = null;
        try {
            fileDto = getFileList(folder, new FileDto(), ftpClient);
        } catch (Exception e) {
        } finally {
            closeFTP(ftpClient);
        }
        return fileDto;
    }

    /**
     * 递归调用查询所有文件以及文件夹
     *
     * @param folder
     * @param fileDto
     * @param ftpClient
     * @return
     */
    public FileDto getFileList(String folder, FileDto fileDto, FTPClient ftpClient) {
        List<FileDto> fileDtos = new ArrayList<>();
        try {
            FTPFile[] ftpFiles = ftpClient.listFiles(folder);
            List<FTPFile> fileList = Arrays.asList(ftpFiles);

            if (CollectionUtils.isEmpty(fileList)) {
                fileDto.setChildren(new ArrayList<>());
                return fileDto;
            }
            for (FTPFile ftpFile : fileList) {
                if (ftpFile.isFile()) {
                    FileDto fileDtoOne = new FileDto();
                    BeanUtils.copyProperties(ftpFile, fileDtoOne);
                    fileDtoOne.setCreateTime(ftpFile.getTimestamp().getTime());
                    String name = ftpFile.getName();
                    int index = name.lastIndexOf(".");
                    fileDtoOne.setFolder(folder);
                    fileDtoOne.setSuffixName(name.substring(index + 1));
                    fileDtos.add(fileDtoOne);
                } else {
                    //文件夹  继续找寻下一级
                    FileDto fileDtoOne = new FileDto();
                    BeanUtils.copyProperties(ftpFile, fileDtoOne);
                    String newFolder = "";
                    if (StringUtils.isBlank(folder)) {
                        newFolder = ftpFile.getName();
                        fileDtoOne.setFolder(newFolder);
                    } else {
                        newFolder = folder + "/" + ftpFile.getName();
                        fileDtoOne.setFolder(newFolder);
                    }
                    fileDtoOne.setCreateTime(ftpFile.getTimestamp().getTime());
                    FileDto children = getFileList(newFolder, fileDtoOne, ftpClient);
                    fileDtos.add(children);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        fileDto.setChildren(fileDtos);
        return fileDto;

    }


    /**
     * 根据ftp文件路径获取文件流
     *
     * @param fileName
     * @return
     */
    public void writeResponse(String fileName, OutputStream out, boolean isPdf, String suffix) {
        FTPClient ftpClient = null;
        InputStream in = null;
        try {
            ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            String pathname = new String(fileName.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            ftpClient.changeWorkingDirectory(pathname);
            FTPFile[] ftpFiles = ftpClient.listFiles(pathname);
            List<FTPFile> ftpFileList = Arrays.asList(ftpFiles);
            if (CollectionUtils.isEmpty(ftpFileList)) {
                throw new BaseException("文件不存在");
            }
            if (ftpFileList.size() == 1) {
                in = ftpClient.retrieveFileStream(pathname);
                // byte[] bytes = toByteArray(in);
                if (isPdf || Arrays.asList(Constants.PIC_SUFFIX).contains(suffix)) {
                    //pdf或图片直接转成流 写出
                    subsectionWriteFile(out, in);
                } else {
                    //不是pdf 先转换pdf 再写出到响应流
                    in = com.person.yhzs.util.FileConvertUtil.convertFtpFile(in, suffix);
                    subsectionWriteFile(out, in);
                }
                //必须先关流
                in.close();
                ftpClient.completePendingCommand();
            } else {
                throw new BaseException("未知的文件路径");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
                closeFTP(ftpClient);
            } catch (IOException e) {
                e.printStackTrace();

            }

        }
    }

//    private void dealTxt(OutputStream out, String charset, InputStream in) {
//        try {
//            BufferedReader br = null;
//            if (charset == "GBK") {
//                subsectionWriteFile(out, in);
//                return;
//            }
//            if (charset == "UTF-8") {
//                br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
//            }
//            String s;
//            while ((s = br.readLine()) != null) {
//                byte[] bytes = s.getBytes("UTF-8");
//                out.write(bytes);
//                System.out.println(s);
//            }
////            System.out.println(new String(s.getBytes("utf-8"), "utf-8"));
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//    }
//
//    private String getTxtCharset(InputStream in) {
//        String charset = "GBK";
//        byte[] first3Bytes = new byte[3];
//        try {
//            boolean checked = false;
//            BufferedInputStream bis = new BufferedInputStream(in);
//            bis.mark(0);
//            int read = bis.read(first3Bytes, 0, 3);
//            if (read == -1) {
//                //文件编码为 ANSI
//                return charset;
//            } else if (first3Bytes[0] == (byte) 0xFF
//                    && first3Bytes[1] == (byte) 0xFE) {
//                //文件编码为 Unicode
//                charset = "UTF-16LE";
//                checked = true;
//            } else if (first3Bytes[0] == (byte) 0xFE
//                    && first3Bytes[1] == (byte) 0xFF) {
//                //文件编码为 Unicode big endian
//                charset = "UTF-16BE";
//                checked = true;
//            } else if (first3Bytes[0] == (byte) 0xEF
//                    && first3Bytes[1] == (byte) 0xBB
//                    && first3Bytes[2] == (byte) 0xBF) {
//                //文件编码为 UTF-8
//                charset = "UTF-8";
//                checked = true;
//            }
//            bis.reset();
//            if (!checked) {
//                int loc = 0;
//                while ((read = bis.read()) != -1) {
//                    loc++;
//                    if (read >= 0xF0) {
//                        break;
//                    }
//                    if (0x80 <= read && read <= 0xBF) {
//                        // 单独出现BF如下的，也算是GBK
//                        break;
//                    }
//                    if (0xC0 <= read && read <= 0xDF) {
//                        read = bis.read();
//                        if (0x80 <= read && read <= 0xBF) {
//                            // 双字节 (0xC0 - 0xDF)
//                            // (0x80
//                            // - 0xBF),也可能在GB编码内
//                            continue;
//                        } else {
//                            break;
//                        }
//                    } else if (0xE0 <= read && read <= 0xEF) {
//                        // 也有可能出错，可是概率较小
//                        read = bis.read();
//                        if (0x80 <= read && read <= 0xBF) {
//                            read = bis.read();
//                            if (0x80 <= read && read <= 0xBF) {
//                                charset = "UTF-8";
//                                break;
//                            } else {
//                                break;
//                            }
//                        } else {
//                            break;
//                        }
//                    }
//                }
//            }
//           // bis.close();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return charset;
//    }


    /**
     * 根据文件夹 搜索指定的文件名 做模糊搜索
     *
     * @param fileName
     * @param currentFolder
     * @return
     */
    public List<FileVo> searchFile(String fileName, String currentFolder) {
        FTPClient ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
        List<FileVo> fileVoList = new ArrayList<>();
        try {
            String fileNameLowerCase = fileName.toLowerCase();
            List<FileVo> fileVos = searchFile(ftpClient, currentFolder, fileVoList, fileNameLowerCase);
            return fileVos;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return fileVoList;
    }

    /**
     * 根据文件夹 搜索指定的文件名 做模糊搜索
     *
     * @param ftpClient
     * @param currentFolder
     * @param fileVos
     * @param fileName
     * @return
     */
    public List<FileVo> searchFile(FTPClient ftpClient, String currentFolder, List<FileVo> fileVos, String fileName) {
        try {
            String pathname = StringUtils.isBlank(currentFolder) ? null : new String(currentFolder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            FTPFile[] ftpFiles = ftpClient.listFiles(pathname);
            List<FTPFile> fileList = Arrays.asList(ftpFiles);
            if (CollectionUtils.isEmpty(fileList)) {
                return fileVos;
            }
            for (FTPFile ftpFile : fileList) {
                if (ftpFile.isFile()) {
                    if (ftpFile.getName().toLowerCase().contains(fileName)) {
                        FileVo fileVo = new FileVo();
                        BeanUtils.copyProperties(ftpFile, fileVo);
                        fileVo.setCreateTime(ftpFile.getTimestamp().getTime());
                        String name = ftpFile.getName();
                        int index = name.lastIndexOf(".");
                        if (StringUtils.isBlank(currentFolder)) {
                            fileVo.setFolder("/");
                            fileVo.setAbsolutePath("/" + ftpFile.getName());
                        } else {
                            fileVo.setFolder(currentFolder);
                            fileVo.setAbsolutePath(currentFolder + "/" + ftpFile.getName());
                        }
                        fileVo.setSuffixName(name.substring(index + 1));
                        fileVos.add(fileVo);
                    }
                } else {
                    String newFolder = "";
                    if (ftpFile.getName().toLowerCase().contains(fileName)) {
                        //文件夹  继续找寻下一级
                        FileVo fileVo = new FileVo();
                        BeanUtils.copyProperties(ftpFile, fileVo);
                        if (StringUtils.isBlank(currentFolder)) {
                            newFolder = "/" + ftpFile.getName();
                            fileVo.setFolder("/");
                            fileVo.setAbsolutePath("/" + ftpFile.getName());
                        } else {
                            newFolder = currentFolder + "/" + ftpFile.getName();
                            fileVo.setFolder(currentFolder);
                            fileVo.setAbsolutePath(currentFolder + "/" + ftpFile.getName());
                        }
                        fileVo.setCreateTime(ftpFile.getTimestamp().getTime());
                        fileVos.add(fileVo);
                        searchFile(ftpClient, newFolder, fileVos, fileName);
                    } else {
                        newFolder = StringUtils.isBlank(currentFolder) ? "/" + ftpFile.getName() : currentFolder + "/" + ftpFile.getName();
                        searchFile(ftpClient, newFolder, fileVos, fileName);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileVos;
    }

    /**
     * 移动文件/文件夹 至指定目录
     *
     * @param fileOrDir
     * @param targetFolder
     * @param isDirectory
     * @return
     */
    public boolean moveFileOrDir(String fileOrDir, String targetFolder, boolean isDirectory) {
        FTPClient ftpClient = null;
        boolean flag = false;
        try {
            ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
            flag = moveDirectory(fileOrDir, targetFolder, ftpClient, isDirectory);
        } catch (Exception e) {
            if (e instanceof InvalidDataException) {
                throw e;
            }
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
        }
        return flag;
    }

    /**
     * 移动文件或文件夹到指定目录
     *
     * @param fileOrDir
     * @param targetFolder
     * @param ftpClient
     * @return
     */
    public boolean moveDirectory(String fileOrDir, String targetFolder, FTPClient ftpClient, boolean isDirectory) {
        boolean flag = false;
        try {
            //原始文件夹是否为根目录
            int index = fileOrDir.lastIndexOf("/");
            String oldFileOrDir = null;
            if (index == 0) {
                //为根目录
                oldFileOrDir = fileOrDir;
            } else {
                oldFileOrDir = fileOrDir.substring(index);
            }
            //检查目标文件夹中是否有相同名的文件夹
            FTPFile[] ftpFiles = ftpClient.listFiles(new String(targetFolder.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
            List<FTPFile> fileList = Arrays.asList(ftpFiles);
            if (!CollectionUtils.isEmpty(fileList)) {
                List<String> dirNames = null;
                if (isDirectory) {
                    dirNames = fileList.stream().filter(FTPFile::isDirectory).map(FTPFile::getName).collect(Collectors.toList());
                } else {
                    dirNames = fileList.stream().filter(FTPFile::isFile).map(FTPFile::getName).collect(Collectors.toList());
                }
                String name = oldFileOrDir.replace("/", "");
                if (dirNames.contains(name)) {
                    throw new InvalidDataException("目标文件夹中包含相同的文件夹名或文件");
                }
            }
            //进行文件夹移动功能
            String target = targetFolder + oldFileOrDir;
            String targetF = new String(target.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO);
            flag = ftpClient.rename(new String(fileOrDir.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO), targetF);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 生成一个zip文件
     *
     * @param srcSource
     * @return
     * @throws Exception
     */
    public void createZip(String srcSource, HttpServletResponse response) {
        FTPClient ftpClient = null;
        ServletOutputStream out = null;
        try {
            ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
            ftpClient.changeWorkingDirectory(new String(srcSource.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
            FTPFile[] ftpFiles = ftpClient.listFiles(new String(srcSource.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
            List<FTPFile> ftpFileList = Arrays.asList(ftpFiles);
            if (CollectionUtils.isEmpty(ftpFileList)) {
                throw new InvalidDataException("当前文件夹为空文件夹，没有任何文件");
            }
            int index = srcSource.lastIndexOf("/");
            String prefix = "";
            if (index != 0) {
                prefix = prefix + srcSource.substring(0, index);
            }
            response.reset();
            out = response.getOutputStream();
            response.addHeader("Access-Control-Allow-Origin", "*");
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            response.setHeader("Content-Disposition", "attachment;fileName=" + "down.zip");
            response.setContentType("application/octet-stream; charset=UTF-8");
            // response.setContentLengthLong(20);
            ZipOutputStream zip = new ZipOutputStream(out);
            //将目标文件打包成zip导出
            compressFile(zip, ftpFileList, srcSource, ftpClient, prefix);
            IOUtils.closeQuietly(zip);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 生成一个zip文件
     *
     * @param srcSource
     * @param response
     * @param downLoadName
     * @return
     * @throws Exception
     */
    public void createZip(String srcSource, HttpServletResponse response, String downLoadName) {
        FTPClient ftpClient = null;
        ServletOutputStream out = null;
        try {
            ftpClient = getFTPClient(ftpHost, ftpPort, ftpUsername, ftpPassword);
            ftpClient.changeWorkingDirectory(new String(srcSource.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
            FTPFile[] ftpFiles = ftpClient.listFiles(new String(srcSource.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
            List<FTPFile> ftpFileList = Arrays.asList(ftpFiles);
            if (CollectionUtils.isEmpty(ftpFileList)) {
                throw new InvalidDataException("当前文件夹为空文件夹，没有任何文件");
            }
            int index = srcSource.lastIndexOf("/");
            String prefix = "";
            if (index != 0) {
                prefix = prefix + srcSource.substring(0, index);
            }
            response.reset();
            out = response.getOutputStream();
            response.addHeader("Access-Control-Allow-Origin", "*");
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            response.setHeader("Content-Disposition", "attachment;fileName=" + downLoadName);
            response.setContentType("application/octet-stream; charset=UTF-8");
            // response.setContentLengthLong(20);
            ZipOutputStream zip = new ZipOutputStream(out);
            //将目标文件打包成zip导出
            compressFile(zip, ftpFileList, srcSource, ftpClient, prefix);
            IOUtils.closeQuietly(zip);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeFTP(ftpClient);
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }


    /**
     * 压缩指定目录中所有文件夹以及文件
     *
     * @param zip         zip输出流
     * @param ftpFileList ftp文件列表
     * @param dir         指定的目录
     * @param ftpClient   ftpClient
     */
    public void compressFile(ZipOutputStream zip, List<FTPFile> ftpFileList, String dir, FTPClient ftpClient, String prefix) {
        try {
            for (FTPFile file : ftpFileList) {
                //如果当前的是文件夹，则进行进一步处理
                if (file.isDirectory()) {
                    String targetDir = dir + "/" + file.getName();
                    ftpClient.changeWorkingDirectory(new String(targetDir.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
                    FTPFile[] ftpFiles = ftpClient.listFiles(new String(targetDir.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
                    //得到文件列表信息
                    List<FTPFile> fileList = Arrays.asList(ftpFiles);
                    if (CollectionUtils.isEmpty(fileList)) {
                        //空目录添加一个节点处理
                        //处理多层级的目录 只压缩最里面的目录
                        ZipEntry dirDirectory = new ZipEntry(dir.replace(prefix, "") + "/" + file.getName() + "/");
                        zip.putNextEntry(dirDirectory);
                    } else {
                        //循环将文件夹中的文件打包
                        compressFile(zip, fileList, targetDir, ftpClient, prefix);
                    }
                } else {
                    //当前的是文件，打包处理
                    //文件输入流
                    String targetDir = dir + "/" + file.getName();
                    InputStream inputStream = ftpClient.retrieveFileStream(new String(targetDir.getBytes(CHARSET_UTF8_OR_GBK), CHARSET_ISO));
                    BufferedInputStream bis = new BufferedInputStream(inputStream);
                    //ZipEntry entry = new ZipEntry(targetDir);
                    ZipEntry entry = new ZipEntry(dir.replace(prefix, "") + "/" + file.getName());
                    zip.putNextEntry(entry);
                    //zip.write(toByteArray(inputStream));
                    subsectionZip(zip, inputStream);
                    IOUtils.closeQuietly(bis);
                    zip.flush();
                    zip.closeEntry();
                    //必须先关流
                    inputStream.close();
                    ftpClient.completePendingCommand();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void subsectionZip(ZipOutputStream zip, InputStream input) throws IOException {
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            zip.write(buffer, 0, n);
        }
        zip.flush();
    }

    /**
     * 分段写入文件流
     *
     * @param out
     * @param input
     * @throws IOException
     */
    public void subsectionWriteFile(OutputStream out, InputStream input) throws IOException {
        byte[] buffer = new byte[4096];
        int n = 0;
        while (-1 != (n = input.read(buffer))) {
            out.write(buffer, 0, n);
        }
        out.flush();

    }


}

